// 引入 lodash 的 isPlainObject 函数
const isPlainObject = require('lodash/isPlainObject');

/**
 * 下划线连接符转驼峰
 * @param {string} str - 待转换的字符串，默认为空字符串
 * @example
 * convertUnderlineToCamel('test_example') // testExample
 * @returns {string}
 */
const convertUnderlineToCamel = function(str = '') {
  return str.toString().replace(/_([a-z])/g, function(_, c) {
    return c ? c.toUpperCase() : '';
  });
};

/**
 * 驼峰转下划线连接符
 * @param {string} str - 待转换的字符串，默认为空字符串
 * @param {boolean} withNum - 是否包含数字转换，默认为 false
 * @example
 * convertCamelToUnderline('testExample') // 'test_example'
 * @returns {string}
 */
const convertCamelToUnderline = function(str = '', withNum = false) {
  return str.replace(withNum ? /\B([A-Z0-9])/g : /\B([A-Z])/g, function(_, c) {
    return c ? '_' + c.toLowerCase() : '';
  });
};

/**
 * 把对象所有的key值转为驼峰
 * @param {Array|Object} object - 待转换的对象，默认为空对象
 * @returns {Array|Object}
 */
const convertObjectKeyToCamel = function(object = {}) {
  if (Array.isArray(object)) {
    return object.map(item => 
      isPlainObject(item) ? convertObjectKeyToCamel(item) : item
    );
  } else if (isPlainObject(object)) {
    const newObject = {};
    for (const [key, value] of Object.entries(object)) {
      newObject[convertUnderlineToCamel(key)] = isPlainObject(value) || Array.isArray(value) ? convertObjectKeyToCamel(value) : value;
    }
    return newObject;
  }
  return object;
};

/**
 * 把对象所有的key值转为下划线连接符
 * @param {Array|Object} object - 待转换的对象，默认为空对象
 * @param {boolean} withNum - 是否包含数字转换，默认为 false
 * @returns {Array|Object}
 */
const convertObjectKeyToUnderline = function(object = {}, withNum = false) {
  if (Array.isArray(object)) {
    return object.map(item => 
      isPlainObject(item) ? convertObjectKeyToUnderline(item, withNum) : item
    );
  } else if (isPlainObject(object)) {
    const newObject = {};
    for (const [key, value] of Object.entries(object)) {
      const fieldKey = convertCamelToUnderline(key, withNum);
      newObject[fieldKey] = isPlainObject(value) || Array.isArray(value) ? convertObjectKeyToUnderline(value, withNum) : value;
    }
    return newObject;
  }
  return object;
};